package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.repository;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowRuTimeoutSettingVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.notice.FlowReNoticeInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.notice.FlowReNoticeInfoQueryVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.notice.NoticeInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowRuTimeoutSettingRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowMessage;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowMessageExample;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowRuTimeoutSetting;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowRuTimeoutSettingExample;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.FlowMessageDAO;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.FlowRuTimeoutSettingDAO;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.NoticeTemplateDAO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author lilh
 * @date 2019-07-11 16:52
 */
@Service
public class FlowRuTimeoutSettingRepositoryImpl implements FlowRuTimeoutSettingRepository {

    @Autowired
    private FlowRuTimeoutSettingDAO flowRuTimeoutSettingDAO;

    @Autowired
    private NoticeTemplateDAO noticeTemplateDAO;
    @Autowired
    private FlowMessageDAO flowMessageDAO;

    @Override
    public int insertFlowRuTimeoutSetting(FlowRuTimeoutSettingVo vo) {
        vo.setCreateTime(new Date());
        vo.setUpdateTime(new Date());
        FlowRuTimeoutSetting entity = convert(vo);
        int count = flowRuTimeoutSettingDAO.insertSelective(entity);
        vo.setId(entity.getId());
        return count;
    }

    @Override
    public List<FlowRuTimeoutSettingVo> listFlowRuTimeoutSetting(String taskId) {
        FlowRuTimeoutSettingExample query = new FlowRuTimeoutSettingExample();
        query.createCriteria().andTaskIdEqualTo(taskId);
        query.setOrderByClause(" update_time asc");
        return listFlowRuTimeoutSetting(query);
    }

    @Override
    public List<FlowRuTimeoutSettingVo> listFlowRuTimeoutSetting(String processInstanceId, String nodeCode, String noticeType) {
        FlowRuTimeoutSettingExample query = new FlowRuTimeoutSettingExample();
        query.createCriteria().andProcInstIdEqualTo(processInstanceId).andActivityIdEqualTo(nodeCode).andTypeEqualTo(noticeType);
        return listFlowRuTimeoutSetting(query);
    }

    private List<FlowRuTimeoutSettingVo> listFlowRuTimeoutSetting(FlowRuTimeoutSettingExample query) {
        List<FlowRuTimeoutSettingVo> collect = flowRuTimeoutSettingDAO.selectByExample(query).stream().map(this::convert).collect(Collectors.toList());
        for (FlowRuTimeoutSettingVo flowRuTimeoutSettingVo:collect){
            FlowMessageExample flowMessageExample=new FlowMessageExample();
            flowMessageExample.createCriteria().andMsgTypeEqualTo(flowRuTimeoutSettingVo.getType()).andTaskIdEqualTo(flowRuTimeoutSettingVo.getTaskId());
            List<FlowMessage> flowMessages = flowMessageDAO.selectByExample(flowMessageExample);
            if (CollectionUtils.isNotEmpty(flowMessages)){
                FlowMessage flowMessage = flowMessages.get(0);
                flowRuTimeoutSettingVo.setTitle(flowMessage.getMsgTitle());
                flowRuTimeoutSettingVo.setContent(flowMessage.getMsgBoby());
            }
        }
        return collect;
    }

    @Override
    public int updateFlowRuTimeoutSetting(FlowRuTimeoutSettingVo entity) {
        entity.setUpdateTime(new Date());
        return flowRuTimeoutSettingDAO.updateByPrimaryKeySelective(convert(entity));
    }

    @Override
    public List<NoticeInfo> listTaskHandleNotice(String procInstId, String activityId) {
        FlowReNoticeInfoQueryVo flowReNoticeInfoQueryVo = new FlowReNoticeInfoQueryVo();
        flowReNoticeInfoQueryVo.setProcInstId(procInstId);
        flowReNoticeInfoQueryVo.setActivityId(activityId);
        return noticeTemplateDAO.listTaskHandleNotice(flowReNoticeInfoQueryVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<FlowReNoticeInfo> listNeedNotifyTimeoutAndWarningNotice(String procId) {
        List<FlowReNoticeInfo> flowReNoticeInfos = noticeTemplateDAO.listNeedNotifyTimeoutAndWarningNotice(procId);
        if (CollectionUtils.isNotEmpty(flowReNoticeInfos)) {
            List<Long> noticeIds = flowReNoticeInfos.stream().map(FlowReNoticeInfo::getId).collect(Collectors.toList());
            noticeTemplateDAO.updateNotice(noticeIds);
        }
        return flowReNoticeInfos;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FlowReNoticeInfo getNeedNotifyTimeoutAndWarningNoticeById(Long id) {
        FlowReNoticeInfo flowReNoticeInfo = noticeTemplateDAO.getNeedNotifyTimeoutAndWarningNoticeById(id);
        if (Objects.nonNull(flowReNoticeInfo)) {
            List<Long> noticeIds = Arrays.asList(flowReNoticeInfo.getId());
            noticeTemplateDAO.updateNotice(noticeIds);
        }
        return flowReNoticeInfo;
    }

    private FlowRuTimeoutSetting convert(FlowRuTimeoutSettingVo vo) {
        if (Objects.isNull(vo)) {
            return null;
        }
        FlowRuTimeoutSetting result = new FlowRuTimeoutSetting();
        BeanUtils.copyProperties(vo, result);
        return result;
    }

    private FlowRuTimeoutSettingVo convert(FlowRuTimeoutSetting entity) {
        if (Objects.isNull(entity)) {
            return null;
        }
        FlowRuTimeoutSettingVo result = new FlowRuTimeoutSettingVo();
        BeanUtils.copyProperties(entity, result);
        return result;
    }

}
